package com.xiao.classloader;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.*;
import java.net.URLClassLoader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Locale;

/**
 * 自定义类加载器
 * 外部文件系统类加载器
 * 主要是改变获取类文件二进制流的方式，可以从磁盘，网络，数据库... 中获取二进制流
 * 在双亲委派机制中，如何确定某一个类可以被哪个类加载器所加载
 * 在代码中，通常可以显式的指定使用某一个类加载器
 *
 * 类加载的结果就是在内存中生成一个 代表目标类的 java.lang.Class对象，作为方法区这个类的各种数据的访问路口
 */
public class CustomClassLoad extends ClassLoader {


    /**
     * 重写 findClass 方法
     * 父类的该方法直接抛出异常，所以该方法必须重写
     * <p>
     * javax.tool 拓展包下面的编译工具
     *
     * @param name 类名
     * @return java.lang.Class
     * @throws ClassNotFoundException
     */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 假设从文件系统重返回一个源文件，然后动态编译加载
        File file = new File(name);
        InputStream fileInputStream = null;
        OutputStream outputStream = null;
        OutputStream errOutPutstream = null;
        try {
            fileInputStream = new FileInputStream(file);
            outputStream = new FileOutputStream("");
            errOutPutstream = new FileOutputStream("");

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //
        JavaCompiler systemJavaCompiler = ToolProvider.getSystemJavaCompiler();

        StandardJavaFileManager standardFileManager = systemJavaCompiler.getStandardFileManager(null, Locale.CHINA, StandardCharsets.UTF_8);


        // 输入流、输出流、异常输出流、String... agrs 编译参数  返回值 int 表示
        systemJavaCompiler.run(fileInputStream, outputStream, errOutPutstream);
        // 编译源文件
        JavaCompiler.CompilationTask task = systemJavaCompiler.getTask(null, standardFileManager, null, null, null, null);

        Boolean result = task.call();
        Class<?> aClass = standardFileManager.getClassLoader(null).loadClass("");
        // todo 未编写完成，待完成


        return super.findClass(name);
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        // 不重写
        return super.loadClass(name);
    }


}
